# Boost Software License - Version 1.0 - August 17th, 2003
#
# Permission is hereby granted, free of charge, to any person or organization
# obtaining a copy of the software and accompanying documentation covered by
# this license (the "Software") to use, reproduce, display, distribute,
# execute, and transmit the Software, and to prepare derivative works of the
# Software, and to permit third-parties to whom the Software is furnished to
# do so, all subject to the following:
#
# The copyright notices in the Software and this entire statement, including
# the above license grant, this restriction and the following disclaimer,
# must be included in all copies of the Software, in whole or in part, and
# all derivative works of the Software, unless such copies or derivative
# works are solely in the form of machine-executable object code generated by
# a source language processor.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
# SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
# FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

# - Enable Code Coverage
#
# 2012-01-31, Lars Bilke
#
# USAGE:
# 1. Copy this file into your cmake modules path
# 2. Add the following line to your CMakeLists.txt:
#      INCLUDE(CodeCoverage)
#
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
#    which runs your test executable and produces a lcov code coverage report.
#

# - Changes made by Celix
# 1. Added compiler options using --coverage instead of GCC specific strings
# 2. Added custom target to generate HTML pages for combined coverage results
# 3. Added each coverage target to the overall "coverage" target
# 4. Added "mock" to exclude list for coverage results
# 5. Removed HTML generation from the coverage setup function
# 6. Removed unneeded Cobertura function
#

# Option to enable/disable coverage
option(ENABLE_CODE_COVERAGE "Enables code coverage" FALSE)

# Check if coverage is enabled
IF(ENABLE_CODE_COVERAGE)

    # Check prereqs
    FIND_PROGRAM( GCOV_PATH gcov )
    FIND_PROGRAM( LCOV_PATH lcov )
    FIND_PROGRAM( GENHTML_PATH genhtml )
    FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)

    IF(NOT GCOV_PATH)
    	MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
    ENDIF() # NOT GCOV_PATH

    #IF(NOT CMAKE_COMPILER_IS_GNUCXX)
    #	MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
    #ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX

    IF ( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" )
      MESSAGE( WARNING "Code coverage results with an optimised (non-Debug) build may be misleading" )
    ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"

    # Setup compiler options
    ADD_DEFINITIONS(--coverage)
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")

    IF(NOT TARGET coverage)
        add_custom_target(coverage
            COMMAND ${CMAKE_COMMAND} -E make_directory coverage_results
            COMMAND ${GENHTML_PATH} -o coverage_results coverage/*.info.cleaned
    	    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
            COMMENT "Generating report.\nOpen index.html in your browser to view the coverage report."
        )

        SET_TARGET_PROPERTIES(coverage PROPERTIES COVERAGE_TARGET_ADDED "")
    ENDIF()

ENDIF(ENABLE_CODE_COVERAGE)

#[[
Setup provided test target for coverage generation.
the <test_target> should be a CMake target created with a add_test CMake command.

setup_target_for_coverage(<test_target>
    [c <dir>]
    [ARGUMENTS arguments...]
)


Optional arguments are:
- SCAN_DIR: The directory used to scan for source files. Default is .
- ARGUMENTS: The arguments to pass to the test runnner
]]
function (setup_target_for_coverage)
    if (ENABLE_CODE_COVERAGE)
        list(GET ARGN 0 TEST_TARGET_NAME)
        list(REMOVE_AT ARGN 0)

        set(OPTIONS )
        set(ONE_VAL_ARGS SCAN_DIR)
        set(MULTI_VAL_ARGS ARGUMENTS)
        cmake_parse_arguments(COVERAGE "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})

    	IF(NOT LCOV_PATH)
    		MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
    	ENDIF() # NOT LCOV_PATH

    	IF(NOT GENHTML_PATH)
    		MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
    	ENDIF() # NOT GENHTML_PATH

        if (NOT COVERAGE_SCAN_DIR)
            set(COVERAGE_SCAN_DIR ".")
        endif()

        set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/coverage/${TEST_TARGET_NAME}.info")

    	# Setup target
        add_custom_target(${TEST_TARGET_NAME}_coverage

    		# Cleanup lcov
    		COMMAND ${LCOV_PATH} --directory . --zerocounters

            COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -R ${TEST_TARGET_NAME}

    		# Capturing lcov counters and generating report
            COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/coverage
    		COMMAND ${LCOV_PATH} --directory ${COVERAGE_SCAN_DIR} --capture --output-file ${OUTPUT_FILE}
    		COMMAND ${LCOV_PATH} --remove ${OUTPUT_FILE} '**/error_injector/*' '**/mock/*' '**/.conan/*' '**/test/*' '**/gtest/*' '**/tst/*' '**/celix/gen/*' '**/googletest_project/*' '**/glog/*' '/usr/*' --output-file ${OUTPUT_FILE}.cleaned

            #test dependencies, so that test is runned
            DEPENDENCIES ${TEST_TARGET_NAME}

            WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    		COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
    	)
        add_dependencies(coverage ${TEST_TARGET_NAME}_coverage)
    endif ()
endfunction ()
